#region Copyright Notice
// 
// 
// Copyright (c) 2009-2010 Anindya Chatterjee
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// 
// 
#endregion
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace System.Serialization
{
    /// <summary>
    /// Serializer tool to (de)serialize IBObject object
    /// </summary>
    /// <typeparam name="T">A class who implements <see cref="IBObject"/> interface</typeparam>
    public class BObjectSerializer<T> where T : IBObject, new()
    {
        private static BinaryFormatter _binaryFormatter;

        /// <summary>Reads object data from a binary file without Decryption.</summary>
        /// <param name="file">Binary file name.</param>
        /// <returns>T object</returns>
        public static T ReadFile(string file)
        {
            return ReadFile(file, false);
        }

        /// <summary>Reads object data from a binary file.</summary>
        /// <param name="file">Binary file name.</param>
        /// <returns>T object</returns>
        /// <param name="decrypt">Decrypt during reading or not</param>
        public static T ReadFile(string file, bool decrypt)
        {
            T bObj;
            _binaryFormatter = new BinaryFormatter();
            var stream = new FileStream(file, FileMode.OpenOrCreate);

            var streamReader = new StreamReader(stream);
            string content = streamReader.ReadToEnd();

            if (decrypt)
                content = Security.Decrypt(content);

            byte[] bytes = StringUtil.StringToBytes(content);
            var memoryStream = new MemoryStream(bytes);
            try
            {
                bObj = (T) _binaryFormatter.Deserialize(memoryStream);
            }
            catch (SerializationException ex)
            {
                Trace.WriteLine(ex);
                bObj = new T();
            }

            memoryStream.Close();
            streamReader.Close();
            stream.Close();
            return bObj;
        }

        /// <summary>Writes object data to binary file without Encryption.</summary>
        /// <param name="file">Binary file name.</param>
        /// <param name="bObj">T object.</param>
        public static bool WriteFile(string file, T bObj)
        {
            return WriteFile(file, bObj, false);
        }

        /// <summary>Writes object data to binary file.</summary>
        /// <param name="file">Binary file name.</param>
        /// <param name="bObj">T object.</param>
        /// <param name="encrypt">Encrypt during saving or not</param>
        public static bool WriteFile(string file, T bObj, bool encrypt)
        {
            bool result = false;
            _binaryFormatter = new BinaryFormatter();
            var stream = new FileStream(file, FileMode.Create);
            var memoryStream = new MemoryStream();
            try
            {
                _binaryFormatter.Serialize(memoryStream, bObj);
                result = true;
            }
            catch (SerializationException ex)
            {
                Trace.WriteLine(ex);
            }
            string content = StringUtil.BytesToString(memoryStream.ToArray());

            if (encrypt)
                content = Security.Encrypt(content);

            var streamWriter = new StreamWriter(stream);
            streamWriter.Write(content);

            memoryStream.Close();
            streamWriter.Close();
            stream.Close();

            return result;
        }
    }
}